概述
前面的几篇关于 Android 事件分发的文章我们简要的介绍过关于多点触控的知识,本章我们就从源码角度进行一些分析。
Android 也是支持多点触控的,当已经有手指接触屏幕的情况下,当再有其他触摸点出现时,会触发 ACTION_POINTER_DOWN
事件(可能被拆分成 ACTION_DOWN 事件),当有手指离开屏幕时会触发 ACTION_POINTER_UP
事件(当然这个事件在某个View上还可能转换为ACTION_UP
事件),最后一根手指离开屏幕是触发 ACTION_UP
事件,因此多点触控的事件可能是下面的流程:
1 | ACTION_DOWN -> ACTION_POINTER_DOWN -> ACTION_POINTER_UP -> ACTION_UP |
获取多点触控获取事件类型请使用 event.getAction() & MotionEvent.ACTION_MASK
或者 getActionMasked()
。追踪事件流可以使用 PointId。
多点触控事件传递流程
为了方便调试,我们模拟了一个环境,布局如下:
1 | <com.example.heqiang.testsomething.event.LinearLayoutA xmlns:android="http://schemas.android.com/apk/res/android" |
然后在 ViewC 和 ViewD 的 onTouchEvent 中收到 MotionEvent.ACTION_DOWN 时返回 true,表示可以处理事件,保证后续的事件可以继续分发下来。
1 | // ViewC |
1 | // ViewD |
然后用一根手指按住 ViewD,此时用另外一根手指点击 ViewC。这样就模拟出了一个多点触控的场景。
下面来看一下事件的传递,这个过程可以分为4个阶段:
1 | //ViewD被按压 |
我们可以看到,在 LinearLayoutA 分发 ACTION_POINTER_DOWN 和 ACTION_POINTER_UP 之前,会把事件拆分成 ACTION_DOWN 和 ACTION_UP 事件,然后分发给它的子 View。
源码分析
dispatchTransformedTouchEvent 的调用有三处,第一处是:
1 | if (actionMasked == MotionEvent.ACTION_DOWN |
当事件为ACTION_DOWN、ACTION_POINTER_DOWN、ACTION_HOVER_MOVE事件时会走这里,表示一个新的事件序列,寻找可以接收事件的目标。
第二处和第三处是下面:
1 | // Dispatch to touch targets. |
在这个阶段是在事件的派发阶段,第二次调用是因为事件没有找到 mFirstTouchTarget 对象,可以认为是没有子 View 消耗事件,最终将事件交给父控件本身处理。
第三次调用是在父控件没有拦截事件的情况下,会将事件分发到子 View 中。
1 | private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel, |
event.getPointerIdBits()
获取的是当前屏幕所有 pointer id,如果是一个触摸点就是 1,2个触摸点就是3,3个触摸点就是7。
前面的文章也介绍过,ViewGroup 是没有重写 onTouchEvent 的,而是在 View.dispatchTouchEvent 调用的,从 dispatchTransformedTouchEvent 可以看到,分发给 子 View 的事件都是经过转换的,因此 onTouchEvent 方法是不会接收多点触控事件,在传入给View的dispatchTouchEvent之前,就已经进行转换。
参考文章
https://blog.csdn.net/dehang0/article/details/104317611
https://juejin.im/post/6844904145749704712
https://www.google.com/search?source=hp&ei=0CtwX4HvDseRr7wPoNuruAI&q=newPointerIdBits+%3D%3D+oldPointerIdBits&oq=newPointerIdBits+%3D%3D+oldPointerIdBits&gs_lcp=CgZwc3ktYWIQAzIHCCEQChCgAVDBCVjBCWCuD2gAcAB4AIAB8gGIAfIBkgEDMi0xmAEAoAECoAEBqgEHZ3dzLXdpeg&sclient=psy-ab&ved=0ahUKEwiBl6nE1YjsAhXHyIsBHaDtCicQ4dUDCAY&uact=5
https://www.jishuwen.com/d/pKCJ/zh-hk
https://wang-zoo.github.io/post/view_event/
https://juejin.im/post/6844904065617362952
https://blog.csdn.net/MoLiao2046/article/details/103737611
http://gityuan.com/2015/09/19/android-touch/